﻿namespace Raven
{
    public class ProjectileBolt : RavenProjectile
    {
        private ProjectileBolt(RavenBot shooter, Vector2 target) : base(EntityType.Bolt, target,
            shooter.GetWorld(), shooter.ID(), shooter.Pos(), shooter.Facing(),
            Constants.Bolt_Damage, Constants.Bolt_BRadius, Constants.Bolt_MaxSpeed, Constants.Bolt_Mass,
            Constants.Bolt_MaxForce)
        {
            Utility.Assert(target != Vector2.zero);
        }

        public override void Update()
        {
            if (!_impacted)
            {
                _velocity = MaxSpeed() * Heading();

                //make sure vehicle does not exceed maximum velocity
                _velocity.Truncate(_maxSpeed);

                //update the position
                _position += _velocity;


                //if the projectile has reached the target position or it hits an entity
                //or wall it should explode/inflict damage/whatever and then mark itself
                //as dead


                //test to see if the line segment connecting the bolt's current position
                //and previous position intersects with any bots.
                RavenBot hit = GetClosestIntersectingBot(_position - _velocity,
                    _position);

                //if hit
                if (hit != null)
                {
                    _impacted = true;
                    _dead = true;

                    //send a message to the bot to let it know it's been hit, and who the
                    //shot came from
                    _world.Dispatcher.DispatchMsg(Constants.SEND_MSG_IMMEDIATELY,
                        _shooterID,
                        hit.ID(),
                        MessageType.Msg_TakeThatMF,
                        _damageInflicted);
                }

                //test for impact with a wall
                Fix dist = 0;
                if (WallIntersectionTests.FindClosestPointOfIntersectionWithWalls(_position - _velocity,
                    _position,
                    ref dist,
                    ref _impactPoint,
                    _world.GetMap().GetWalls()))
                {
                    _impacted = true;
                    _dead = true;

                    _position = _impactPoint;
                }
            }

            base.Update();
        }

        public class ProjectileBoltPool
        {
            private EntityPool _pool;
            public ProjectileBoltPool(EntityPool pool)
            {
                _pool = pool;
            }
            
            public ProjectileBolt New(RavenBot shooter, Vector2 target)
            {
                ProjectileBolt pb = _pool.GetEntity<ProjectileBolt>(EntityType.Bolt);
                if (pb == null)
                {
                    return new ProjectileBolt(shooter, target);
                }
                
                pb._target = target;
                pb._shooterID = shooter.ID();
                pb._origin = shooter.Pos();
                pb._heading = shooter.Facing();
                pb._timeOfCreation = shooter.GetWorld().GetTimer().currentTime;
                pb._position = shooter.Pos();
                pb._dead = false;
                pb._impacted = false;
                return pb;
            }
        }
    }
}